#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <ctime>
#include <unistd.h>
#include <jsoncpp/json/json.h>

// #define SELF 1

namespace protocol_ns
{
    const std::string SEP = "\r\n";
    const std::string ProtSep = " ";

    // "len"\r\n"{             }"\r\n;

    // 添加协议
    std::string Encode(const std::string &json_str)
    {
        int json_str_len = json_str.size();
        std::string proto_str = std::to_string(json_str_len);
        proto_str += SEP;
        proto_str += json_str;
        proto_str += SEP;

        return proto_str;
    }

    // "len"\r\n"{
    // "len"\r\n"{             }"
    // "len"\r\n"{             }"\r\n;
    // "len"\r\n"{             }"\r\n"len";
    // "len"\r\n"{             }"\r\n"len"\r\n"{             }";
    // "len"\r\n"{             }"\r\n"len"\r\n"{             }"\r\n

    // 获取报文
    std::string Decode(std::string &inbuffer)
    {
        ssize_t pos = inbuffer.find(SEP);
        if (pos == std::string::npos)
            return "";
        std::string len_str = inbuffer.substr(0, pos);
        int packlen = std::stoi(len_str);

        int totallen = packlen + len_str.size() + 2 * SEP.size();
        if (inbuffer.size() < totallen)
            return "";

        std::string package = inbuffer.substr(pos + SEP.size(), packlen);
        inbuffer.erase(0, totallen);
        return package;
    }

    class Request
    {
    public:
        Request() {}
        Request(int x, int y, int oper) : _x(x), _y(y), _oper(oper)
        {
        }

        // 序列化
        bool Serialize(std::string *out)
        {
#ifdef SELF
            //"len\r\nx op y\r\n" : \r\n不输入报文的一部分
            *out = std::to_string(_x) + ProtSep + _oper + ProtSep + std::to_string(_y);
            return true;
#else
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["oper"] = _oper;

            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }

        // 反序列化
        bool Deserialize(const std::string &in)
        {
#ifdef SELF
            //"len\r\nx op y\r\n" : \r\n不输入报文的一部分
            auto left = in.find(ProtSep);
            if (left == std::string::npos)
                return false;
            auto right = in.rfind(ProtSep);
            if (right == std::string::npos)
                return false;
            if (left + ProtSep.size() + 1 != right)
                return false;

            _x = std::stoi(in.substr(0, left));
            _y = std::stoi(in.substr(right + ProtSep.size()));
            _oper = in[left + ProtSep.size()];

            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
#endif
        }

    public:
        int _x;
        int _y;
        char _oper;
    };

    class Response
    {
    public:
        Response(int result = 0, int code = 0) : _result(result), _code(code)
        {
        }

        // 序列化
        bool Serialize(std::string *out)
        {
#ifdef SELF
            //"len\r\nresult code\r\n" : \r\n不输入报文的一部分
            *out = std::to_string(_result) + ProtSep + std::to_string(_code);
            return true;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }

        // 反序列化
        bool Deserialize(const std::string &in)
        {
#ifdef SELF
            //"len\r\nresult code\r\n" : \r\n不输入报文的一部分
            auto min = in.find(ProtSep);
            if (min == std::string::npos)
                return false;
            std::string leftstr = in.substr(0, min);
            std::string rightstr = in.substr(min + ProtSep.size());
            _result = std::stoi(leftstr);
            _code = std::stoi(rightstr);

            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _result = root["result"].asInt();
            _code = root["code"].asInt();

            return true;
#endif
        }

    public:
        int _result; // 结果
        int _code;   // 0:success 1: 除0 2:模0  3.非法操作
    };

    class Factory
    {
    public:
        Factory()
        {
            srand(time(nullptr) ^ getpid());
            opers = "+-*/%^&";
        }

        std::shared_ptr<Request> BuildRequest()
        {
            int x = rand() % 10 + 1;
            usleep(x * 10);
            int y = rand() % 5;
            usleep(y * x * 5);
            char oper = opers[rand() % opers.size()];
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, oper);
            return req;
        }

        std::shared_ptr<Response> BuileResponse()
        {
            return std::make_shared<Response>();
        }

    private:
        std::string opers;
    };
}
